/***********************************************************************
* Code contenant les fonctions qui doivent etre adaptees par           *
* l'etudiant pour son TP note                                          *
***********************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
/* Added */
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <error.h>
void handle_connection (int connection_fd);

void *thread_gestion_connexion_entrante(void *arg);


/*************************************/
/* Definition des variables globales */
/*************************************/
int compteurReponse;

pthread_mutex_t mutex; /* Mutex */

int fd; /* File descriptor */

pthread_t threadImpr;

void *attenteEcriture(void *arg);

/********************************************/
/* Procedures appelees par le reste du code */
/********************************************/

/* Procedure chargee de toutes les initialisations specifiques au code de
   l'etudiant */
void init(){
  int rc;
  pthread_mutex_init(&mutex, NULL); /* Init mutex */
  if (access("sauvegardeCompteurReponse",F_OK) == 0) {
    /* File exists */
    if (access("sauvegardeCompteurReponse",R_OK | W_OK) == 0) {
      fd = open ("sauvegardeCompteurReponse",O_RDWR);
      if (fd == -1) { perror("can't open"); exit(EXIT_FAILURE); } 
      /* Read value... */
      if (read(fd, &compteurReponse, sizeof(int)) < 0) {
        perror("Error reading value");
        exit(EXIT_FAILURE);
      }
    }
    else {
      fprintf(stderr, "File 'sauvegardeCompteurReponse' is not readable/writable");
      exit(EXIT_FAILURE);
    }
  }
  else {
    /* file does not exists */
    fd = open ("sauvegardeCompteurReponse",O_RDWR | O_CREAT,0666);
    if (fd == -1) { perror("can't open"); exit(EXIT_FAILURE); } 
    compteurReponse = 0;
  }
  /* Create writing thread */
  rc = pthread_create(&threadImpr, NULL, attenteEcriture, NULL);
  if(rc) {
    error(EXIT_FAILURE, rc, "pthread_create");
  }
  /*Detachement */
  if (pthread_detach(threadImpr) != 0) {
    error(EXIT_FAILURE, rc, "pthread_detach");
  }
}
void *attenteEcriture(void *arg) {
  do {
    /* Saving value */
    if (lseek(fd, 0, SEEK_SET) < 0) { /* Seeking to begining of  file */
      perror("error lseeking");
      exit(EXIT_FAILURE);
    }
    if (write(fd, &compteurReponse, sizeof(int)) != sizeof(int)) {
      perror("error writing");
      exit(EXIT_FAILURE);
    }
    /* sleeping */
    sleep(1);  
  } while(1); 
}
/* Procedure chargee de la gestion d'une connexion entrante (liee a une requete 
   http */
void gestion_connexion_entrante(int connexion_fd){
  pthread_t thread;
  int rc;
  /* On cree le thread */
  rc = pthread_create(&thread, NULL, thread_gestion_connexion_entrante, (void*)connexion_fd);
  if (rc < 0){
    perror("pthread_create");
    exit(EXIT_FAILURE); 
  }
  /* On detache le thread de sorte que, quand il se terminera, les ressources */
  /* qu'il utilise pourront etre liberees.                                    */
  rc = pthread_detach(thread);
  if (rc < 0){
    perror("pthread_detach");
    exit(EXIT_FAILURE);
  }
}

/* Fonction chargee de faire les traitements lies a compteurReponse lorsque le serveur
   repond a une requete http. Cette focntion doit au minimum incrementer compteurReponse.
   Cette fonction renvoie la valeur de compteurReponse. */
int gestion_compteurReponse(){
  pthread_mutex_lock(&mutex);
  compteurReponse += 1;
  pthread_mutex_unlock(&mutex);
  return compteurReponse;
}


/********************************************/
/* Procedures specifiques a l'etudiant      */
/********************************************/

/* Procedure chargee des traitements liees a une reponse a une requete http */
void *thread_gestion_connexion_entrante(void *arg){
  int connection_fd = (int) arg;
  handle_connection(connection_fd);
  pthread_exit(NULL);
}


